#ifndef _LEXICO_C
#define _LEXICO_C

#include<conio.h>
#include<stdio.h>
#include<string.h>

#include "lexico.h"

int caracter;
int TokenId;
int EstadoActual;
int TipoToken;
int yylval;
int Salir;
int CaracteresLeidos;
int IndiceTabla;
int Agregar;
int AgregarEnTabla;
int ReProcesarCaracter;

FILE *_ArchivoFuente;
FILE *_ArchivoTokens;
FILE *_ArchivoDebug;

char TokenActual[LongitudToken];
int LongitudTokenActual;
char TokenTemp[LongitudToken];
int LongitudTokenTemp;
int PosicionTextoTemp;
char NombreTipoToken[LongitudToken];
int LineaActual;
int PComa;


TablaDeSimbolos Tabla[500];

int EsPalabraReservada(char * token)
{
 int resultado;

 resultado = ttk_Identificador;
 
 if(strcmp(token, "MAIN") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "IF") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "ELSE") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "WHILE") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "INLIST") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "ROUND") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "TRUNC") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "DEFINE") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "ENDDEFINE") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "PRINT") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "FLOAT") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "INTEGER") == 0){resultado = ttk_Pal_Res;}
 if(strcmp(token, "STRING") == 0){resultado = ttk_Pal_Res;}

 return resultado;
}

void BuscarNombreTipoToken(int tipo)
{
 switch(tipo)
 {
   case ttk_Identificador: strcpy(NombreTipoToken, "Id"); //Identificador
                           break;
   case ttk_Cte_Num: strcpy(NombreTipoToken, "CteN"); // CteNumerica
                     break;
   case ttk_Cte_Str: strcpy(NombreTipoToken, "CteS"); //CteString
                     break;
   case ttk_Pal_Res: strcpy(NombreTipoToken, "PR"); //Palabra Reservada
                     AgregarEnTabla = 0;
                     break;
   case ttk_Terminal: strcpy(NombreTipoToken, "ET"); //Elemento Terminal
                      break;
   default:  strcpy(NombreTipoToken, "TD"); //TipoDesconocido
             break;
 }
}
/*****************FUNCIONES LEXICAS***************************/
void Inic_Id(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
}

void Cont_Id(void)
{
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
}
void Fin_Id(void)
{
   Agregar = 1;
   AgregarEnTabla = 1;
   TipoToken = EsPalabraReservada(TokenActual);
   ReProcesarCaracter = 1;
}
void ICte_Num(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Cte_Num;
}
void CCte_Num(void)
{
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
}
void FCte_Num(void)
{
   Agregar = 1;
   AgregarEnTabla = 1;
   ReProcesarCaracter = 1;
}
void ICte_Str(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Cte_Str;
}
void CCte_Str(void)
{
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   if(LongitudTokenActual > (LongitudCteSTR+1))
   {
      printf("%d %d", LongitudTokenActual, LongitudCteSTR+1);
      ERROR();
      printf("La constante String es muy larga \n");
      Salir = 1;                       
   }
}
void FCte_Str(void)
{
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   Agregar = 1;
   AgregarEnTabla = 1;
}
void Op_Suma(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;  
   Agregar = 1;
}
void Op_Resta(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Mult(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Div(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Comp(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Dist(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Par_Abre(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Par_Cier(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void COtraBas(void)
{
   if((char)caracter == ',')
   {
      PComa = LongitudTokenActual;
   }
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   printf("%s \n", TokenActual);
}
void FOtraBas(void)
{
   int x,NoHexa, NoBinario, Base;
   NoHexa = 0;
   NoBinario = 0;
   Base = 0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   for(x = 1; x < PComa; x++)
   {
      if(!((TokenActual[x] == '0') || (TokenActual[x] == '1')))
      {
       NoBinario = 1;
      }
      if(!((((int)TokenActual[x] >= 65) && ((int)TokenActual[x] <= 70)) || (((int)TokenActual[x] >= 97) && ((int)TokenActual[x] <= 103)) || (((int)TokenActual[x] >= 48) && ((int)TokenActual[x] <= 57))))
      {
       NoHexa = 1;
      }
   }
   if((NoHexa == 1) && (NoBinario = 1))
   {
      ERROR();
      printf("el valor no corresponde a ninguna base conocida. \n");
      Salir = 1;                       
   }
   else
   {
      for(x = PComa+1; x < LongitudTokenActual; x++)
      {
       if(((int)TokenActual[x] >= 48) && ((int)TokenActual[x] <= 57))
       {
           Base = (Base * 10) + ((int)TokenActual[x]-48) ;
       }
      }
      if((Base != 2) && (Base != 16))
      {
       ERROR();
       printf("La base no es correcta. \n");
       Salir = 1;      
      }
      else
      {
        if((NoBinario == 1)&&(Base == 2))
        {
         ERROR();
         printf("La base no corresponde con el valor. \n");
         Salir = 1;
        }
        else
        {
         Agregar = 1;      
         AgregarEnTabla = 1;         
        }
      }
   }
}
void Op_MenIg(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_MayIg(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void OpComent(void)
{
// no hago nada porque es comentario
 Agregar = 0;
}
void Coment(void)
{
// no hago nada porque es comentario
 Agregar = 0;
}
void FOpComen(void)
{
// no hago nada porque es comentario
 Agregar = 0;
}
void OpComen2(void)
{
// no hago nada porque es comentario N2
 Agregar = 0;
}
void Comen2(void)
{
// no hago nada porque es comentario N2
 Agregar = 0;
}
void FOpCome2(void)
{
// no hago nada porque es comentario N2  
 Agregar = 0;
}
void Op_And(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Or(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Coma(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Punto(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_2Punt(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_PunYC(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_CorAb(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_CorCi(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_LlavA(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_LlavC(void)
{
   LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
}
void Op_Enter(void)
{
  LongitudTokenActual=0;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   TokenId++;
   TipoToken = ttk_Terminal;
   Agregar = 1;
  
}

void ReProce(void)
{
   int x;
   TokenActual[LongitudTokenActual++] = (char)caracter;
   TokenActual[LongitudTokenActual] = '\0';
   //printf("1_%s_ESTADO:%d, LongitudTokenActual:%d \n", TokenActual, EstadoActual, LongitudTokenActual);
   for(x = 1; x < LongitudTokenActual; x++)
   {
      TokenTemp[x-1] = TokenActual[x];
      TokenActual[x] = '\0';
   }
   PosicionTextoTemp = 0;
   LongitudTokenTemp = LongitudTokenActual - 1;
   TokenActual[1] = '\0';
   LongitudTokenActual = 1;
   TipoToken = ttk_Terminal;
   Agregar = 1;
   //printf("2_%s_ESTADO:%d, LongitudTokenTemp:%d \n", TokenTemp, EstadoActual, LongitudTokenTemp);
   //printf("3_%s_ESTADO:%d, LongitudTokenActual:%d \n", TokenActual, EstadoActual, LongitudTokenActual);
} 

void FIN(void)
{

}
void ERROR(void)
{
 printf("Error en la linea:%d, Fijate cuando escribis :D. \n", LineaActual);     
}
/*****************FUNCIONES LEXICAS***************************/


int Matriz_Estados[][CantidadEventos]=
   {
//   0_ 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_ 9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25                                      
//   !_ "_ &_ (_ )_ *_ +_ ,_ -_ ._ /_ N_ :_ ;_ <_ =_ >_ l_ [_ ]_ L_ {_ |_ }_Enter_TabSpace
   {16, 5,30, 6,10,13,11,32,12,CE,18, 2,33,34,26,14,24, 1,CE,CE, 1,CE,28,CE,CE,CE,},     //ESTADO 0
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE, 1,CE,CE,CE,CE,CE, 1,CE,CE, 1,CE,CE,CE,CE,CE,},     //ESTADO 1
   {CE,CE,CE,CE,CE,CE,CE,CE,CE, 3,CE, 2,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 2
   {EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE, 4,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,},     //ESTADO 3
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE, 4,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 4
   { 5,CE, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,EE, 5,},     //ESTADO 5
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE, 7,CE,CE,CE,CE,CE, 7,CE,CE, 7,CE,CE,CE,CE,CE,},     //ESTADO 6
   {CE,EE,EE,CE,EE,CE,CE, 8,CE,EE,CE, 7,EE,EE,CE,CE,CE, 7,CE,EE, 7,EE,EE,EE,EE, 7,},     //ESTADO 7
   {EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE, 9,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE, 8,},     //ESTADO 8
   {EE,EE,EE,EE,CE,EE,EE,EE,EE,EE,EE, 9,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,},     //ESTADO 9
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 10
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 11
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 12
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 13
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,15,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 14
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 15
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,17,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 16
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 17
   {19,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 18
   {23,19,19,19,19,19,19,19,19,19,20,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,},     //ESTADO 19
   {21,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,},     //ESTADO 20
   {22,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,},     //ESTADO 21
   {22,21,21,21,21,21,21,21,21,21,19,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,},     //ESTADO 22
   {23,19,19,19,19,19,19,19,19,19,CE,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,},     //ESTADO 23
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,25,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 24
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 25
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,27,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 26
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 27
   {EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,29,EE,EE,EE,},     //ESTADO 28
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 29
   {EE,EE,31,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,EE,},     //ESTADO 30
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 31
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 32
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 33
   {CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,CE,},     //ESTADO 34
   };

void (*Matriz_Funciones[][CantidadEventos])()=
   {
//                      !_       "_       &_       (_       )_       *_       +_       ,_       -_       ._       /_       N_       :_       ;_       <_       =_       >_       l_       [_       ]_       L_       {_       |_       }_   Enter_TabSpace_
/*ESTADO  0*/   { Op_Dist,ICte_Str,  Op_And,Par_Abre,Par_Cier, Op_Mult, Op_Suma, Op_Coma,Op_Resta,Op_Punto,  Op_Div,ICte_Num,Op_2Punt,Op_PunYC,Op_MenIg, Op_Comp,Op_MayIg, Inic_Id,Op_CorAb,Op_CorCi, Inic_Id,Op_LlavA,   Op_Or,Op_LlavC,Op_Enter,     FIN,},     //ESTADO 0
/*ESTADO  1*/   {  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,CCte_Num,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id, Cont_Id,  Fin_Id,  Fin_Id, Cont_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,  Fin_Id,},     //ESTADO 1
/*ESTADO  2*/   {FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num, Cont_Id,FCte_Num,CCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,},     //ESTADO 2
/*ESTADO  3*/   {   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,CCte_Num,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,},     //ESTADO 3
/*ESTADO  4*/   {FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,CCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,FCte_Num,},     //ESTADO 4
/*ESTADO  5*/   {CCte_Str,FCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,CCte_Str,   ERROR,CCte_Str,},     //ESTADO 5
/*ESTADO  6*/   {     FIN, ReProce,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,COtraBas,     FIN,     FIN,     FIN,     FIN,     FIN,COtraBas, ReProce,     FIN,COtraBas,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 6
/*ESTADO  7*/   { ReProce,   ERROR,   ERROR, ReProce,   ERROR, ReProce, ReProce,COtraBas, ReProce,   ERROR, ReProce,COtraBas,   ERROR,   ERROR, ReProce, ReProce, ReProce,COtraBas,   ERROR,   ERROR,COtraBas,   ERROR,   ERROR,   ERROR,   ERROR,     FIN,},     //ESTADO 7
/*ESTADO  8*/   {   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,COtraBas,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,     FIN,},     //ESTADO 8
/*ESTADO  9*/   {   ERROR,   ERROR,   ERROR,   ERROR,FOtraBas,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,COtraBas,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,},     //ESTADO 9
/*ESTADO 10*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 10
/*ESTADO 11*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 11
/*ESTADO 12*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 12
/*ESTADO 13*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 13
/*ESTADO 14*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN, Op_Comp,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 14
/*ESTADO 15*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 15
/*ESTADO 16*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN, Op_Dist,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 16
/*ESTADO 17*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 17
/*ESTADO 18*/   {OpComent,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 18
/*ESTADO 19*/   {FOpComen,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,OpComen2,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,},     //ESTADO 19
/*ESTADO 20*/   {OpComen2,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,},     //ESTADO 20
/*ESTADO 21*/   {FOpCome2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,},     //ESTADO 21
/*ESTADO 22*/   {FOpCome2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,  Comen2,},     //ESTADO 22
/*ESTADO 23*/   {FOpComen,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,FOpComen,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,  Coment,},     //ESTADO 23
/*ESTADO 24*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,Op_MenIg,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 24
/*ESTADO 25*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 25
/*ESTADO 26*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,Op_MayIg,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 26
/*ESTADO 27*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 27
/*ESTADO 28*/   {   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   Op_Or,   ERROR,   ERROR,   ERROR,},     //ESTADO 28
/*ESTADO 29*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 29
/*ESTADO 30*/   {   ERROR,   ERROR,  Op_And,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,   ERROR,},     //ESTADO 30
/*ESTADO 31*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 31
/*ESTADO 32*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 32
/*ESTADO 33*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 33
/*ESTADO 34*/   {     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,     FIN,},     //ESTADO 34
   };


void ConfigurarLex(FILE *ArchivoFuente, FILE *ArchivoTokens, FILE *ArchivoDebug)
{
 _ArchivoFuente = ArchivoFuente;
 _ArchivoTokens = ArchivoTokens;
 _ArchivoDebug = ArchivoDebug;
}

void yylex(void)
{
 int Columna;
 int Salir;
 CaracteresLeidos = 0;
 TokenId = 0;
 LineaActual = 1;
 Salir = 0;
 IndiceTabla = 0;
 caracter = getc(_ArchivoFuente);
 ReProcesarCaracter = 0;

 // Recorre el archivo fuente.
 while(!feof(_ArchivoFuente) && (Salir == 0))
 {
   EstadoActual = 0;
   LongitudTokenActual = 0;
   Agregar=0;
   AgregarEnTabla = 0;
   while(!feof(_ArchivoFuente) && (EstadoActual != CantidadEstados) && (EstadoActual >= 0) && (Salir == 0))
   {
     // Valida el caracter y devuelve la columna en la que se encuentra en la matriz de funciones.
     Columna = ValidarCaracter(caracter);
     // printf("caracter: %c(%d), columna: %d, EstadoActual:%d \n", caracter, caracter, Columna, EstadoActual);
     if(Columna == tk_Error)
     {
       // Si paso por aca es que el usuario ingreso un caracter no valido en el programa.
       ERROR();
       Salir = 1;
     }
     else
     {
        if((EstadoActual >=0) && (EstadoActual < CE) && (Columna >=0) && (Columna < CantidadEventos))
        {
          // Ejecuto la funcion que resuelve el caracter leido
         (*Matriz_Funciones[EstadoActual][Columna])();
         
         // Desplazo el automata al nuevo estado dependiendo del caracter leido
         EstadoActual = Matriz_Estados[EstadoActual][Columna];
        }
        else
         printf("Hay problemas: %d, %d \n", EstadoActual, Columna);    

        if(LongitudTokenTemp > 0)
        {
         printf("TokenTemp: %s, PosicionTextoTemp: %d, LongitudTokenTemp: %d,caracter:%c, EstadoActual:%d, TokenTemp:%s.\n", TokenTemp, PosicionTextoTemp, LongitudTokenTemp, caracter, EstadoActual, TokenTemp);
         caracter = TokenTemp[PosicionTextoTemp++];
         if(PosicionTextoTemp == LongitudTokenTemp)
         {
          LongitudTokenTemp = 0;
         }
         //printf("temp: LongitudTokenTemp: %d \n",LongitudTokenTemp);
        }
        else
        {
           if(ReProcesarCaracter == 0)
           {
            //printf("leercaracter: %s. , %c, ESTADO:%d \n", TokenActual, caracter, EstadoActual);
            caracter = getc(_ArchivoFuente);
           }
           else
           {
            //printf("reprocesar: %c, ESTADO:%d \n", TokenActual, caracter, EstadoActual);
            ReProcesarCaracter = 0;
           }
        }
    }
   }
   if((Salir == 0) && (Agregar == 1))
   {
    BuscarNombreTipoToken(TipoToken);
    if(AgregarEnTabla == 1)
    {
     yylval = AgregarTokenEnLista(TokenActual, TipoToken);
    }
    else
    {
     yylval = -1;
    }
    fprintf(_ArchivoTokens, "<%s:%s>", NombreTipoToken, TokenActual);
    fprintf(_ArchivoDebug, "Token Id:%d, Token Nombre:%s, Posicion en tabla:%d, Tipo Token:%s, linea:%d. \n", TokenId, TokenActual, yylval, NombreTipoToken, LineaActual);
   }
 }
}

int AgregarTokenEnLista(char *token, int tipoToken)
{
 int x,Encontra;
 Encontra = 0;
 for(x=0; ((x < IndiceTabla)&&(Encontra == 0)); x++)
 {
   if(strcmp(Tabla[x].nombre, token) == 0)
   {
    Encontra = 1;
   }
 }
 if(Encontra==0)
 {
  Tabla[IndiceTabla].id = IndiceTabla;
  strcpy(Tabla[IndiceTabla].nombre, token);
  Tabla[IndiceTabla].tipoToken = tipoToken;
  Tabla[IndiceTabla].tipoDato = 0;
  Tabla[IndiceTabla].valor[0] = '\0';
  x = IndiceTabla;
  IndiceTabla++;
 }
 return x;
}

void MostrarLista(void)
{
 int x;
 printf("ID\t\tNombre\t\t\tTipoToken\t\tTipoDato\t\tValor\n");
 for(x=0; x < IndiceTabla; x++)
 {
  printf("%d\t\t%s\t\t\t\%d\t\t\t%d\t\t\t%s\n", Tabla[x].id, Tabla[x].nombre, Tabla[x].tipoToken, Tabla[x].tipoDato, Tabla[x].valor);          
 } 
}

int ValidarCaracter(int caracter)
{
 int columna = tk_Error;

 // Entre 65 y 90
 if((caracter >= 'A') && (caracter <= 'Z'))
  columna = tk_LetraMayu;
 else
   // Entre 48 y 57
   if((caracter >= '0') && (caracter <= '9')) 
     columna = tk_digito;
   else  
     // Entre 97 y 122
     if((caracter >= 'a') && (caracter <= 'z'))
       columna = tk_LetraMin;
     else
       // Entre 9 y 32
       if((caracter == 9) || (caracter == 32))
         columna = tk_TabSpace;
       else
       {         
         switch(caracter)
         {
          case 10 : columna = tk_Enter;
                    LineaActual++;    
                break;
          case '!' : columna = tk_Oper_Neg;   // 33
                break;               
          case '"' : columna = tk_Comilla;    // 34
                break;               
          case '&' : columna = tk_Oper_And;   // 38
                break;               
          case '(' : columna = tk_Par_Abre;   // 40
                break;               
          case ')' : columna = tk_Par_Cierra; // 41
                break;               
          case '*' : columna = tk_Oper_Multi; // 42
                break;               
          case '+' : columna = tk_Oper_Sum;   // 43
                break;               
          case ',' : columna = tk_Coma;       // 44
                break;               
          case '-' : columna = tk_Oper_Resta; // 45
                break;               
          case '.' : columna = tk_Punto;      // 46
                break;               
          case '/' : columna = tk_Oper_Div;   // 47
                break; 
          case ':' : columna = tk_DosPuntos;  // 58
                break; 
          case ';' : columna = tk_PuntoComa;  // 59
                break; 
          case '<' : columna = tk_Oper_Menor; // 60
                break; 
          case '=' : columna = tk_Oper_Igual; // 61
                break; 
          case '>' : columna = tk_Oper_Mayor; // 62
                break; 
          case '[' : columna = tk_Cor_Abre;   // 91
                break;
          case ']' : columna = tk_Cor_Cierra; // 93
                break;   
          case '{' : columna = tk_Llave_Abre; // 123
                break;   
          case '|' : columna = tk_Oper_OR;    // 124
                break;   
          case '}' : columna = tk_Llave_Cier; // 125
                break;   
         }
       }
 
 return columna;   
}

#endif


